/*
 * File: ManagerBean.java
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package tvseries.beans;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Logger;
import org.hibernate.ObjectNotFoundException;

import tvseries.entity.Episode;
import tvseries.entity.Series;
import tvseries.utils.DataUtil;
import tvseries.utils.FacesUtil;
import tvseries.utils.FileUtil;
import tvseries.utils.HibernateUtil;
import tvseries.utils.PropUtil;

/**
 * JSF interface bean class for managing the application.
 * 
 * @author nish.naidoo@gmail.com
 * 
 */
public class ManagerBean
{
	private static final Logger log = Logger.getLogger(ManagerBean.class);

	private SeriesBean seriesBean = null;
	private List<SeriesBean> series = null;
	private List<String> actions = null;

	public ManagerBean()
	{
		series = new ArrayList<SeriesBean>();
		setSeries(getSeriesList());
	}

	public String addSeriesView()
	{
		seriesBean = new SeriesBean();
		return ActionResult.SUCCESS;
	}

	public String addSeries()
	{
		if (seriesBean.getId() == null || seriesBean.getId().equals(""))
		{
			FacesUtil.addMessage("main", "IMDB Code is required.");
			return ActionResult.FAILURE;
		}
		else if (seriesBean.getTitle() == null || seriesBean.getTitle().equals(""))
		{
			FacesUtil.addMessage("main", "Series Title is required.");
			return ActionResult.FAILURE;
		}

		Series series = null;
		try
		{
			series = (Series) HibernateUtil.load(Series.class, seriesBean.getId());
		}
		catch (ObjectNotFoundException e)
		{
			series = new Series();
		}

		series.setId(seriesBean.getId());
		series.setTitle(seriesBean.getTitle());
		series.setImdbUrl(PropUtil.get("imdb.url.base") + seriesBean.getId());

		HibernateUtil.persist(series);
		refreshSeries();

		FacesUtil.addMessage("main", "Added series: " + series.getTitle());
		seriesBean = new SeriesBean();

		return ActionResult.SUCCESS;
	}

	public String refreshSeries()
	{
		setSeries(getSeriesList());

		return ActionResult.SUCCESS;
	}

	public String scanAndRename()
	{
		actions = FileUtil.scanAndRename();

		return ActionResult.SUCCESS;
	}

	/**
	 * @return the series
	 */
	public List<SeriesBean> getSeries()
	{
		return series;
	}

	/**
	 * @param series the series to set
	 */
	public void setSeries(List<SeriesBean> series)
	{
		this.series = series;
	}

	/**
	 * @return the seriesBean
	 */
	public SeriesBean getSeriesBean()
	{
		return seriesBean;
	}

	/**
	 * @param seriesBean the seriesBean to set
	 */
	public void setSeriesBean(SeriesBean seriesBean)
	{
		this.seriesBean = seriesBean;
	}

	/**
	 * @return the actions
	 */
	public List<String> getActions()
	{
		return actions;
	}

	/**
	 * @param actions the actions to set
	 */
	public void setActions(List<String> actions)
	{
		this.actions = actions;
	}

	public String selectAllSeries()
	{
		for (SeriesBean s : getSeries())
			s.setSelected(true);

		return ActionResult.SUCCESS;
	}

	public String deselectAllSeries()
	{
		for (SeriesBean s : getSeries())
			s.setSelected(false);

		return ActionResult.SUCCESS;
	}

	public String updateSelectedSeries()
	{
		for (SeriesBean s : getSeries())
		{
			try
			{
				if (s.isSelected())
					DataUtil.updateSeries(s.getId());
			}
			catch (Exception e)
			{
				log.error("Error updating series: " + s.getId());
				log.error(e.getMessage(), e);
			}
		}

		refreshSeries();

		return ActionResult.SUCCESS;
	}

	public String deleteSelectedSeries()
	{
		for (SeriesBean s : getSeries())
		{
			try
			{
				if (s.isSelected())
					DataUtil.deleteSeries(s.getId());
			}
			catch (Exception e)
			{
				log.error("Error updating series: " + s.getId());
				log.error(e.getMessage());
			}
		}

		refreshSeries();

		return ActionResult.SUCCESS;
	}

	public String viewSeries()
	{
		String seriesId = FacesUtil.getRequestParameter("seriesId");
		SeriesBean series = getSeries(seriesId);
		if (series == null)
		{
			log.error("Error viewing series.");
			return ActionResult.ERROR;
		}

		FacesUtil.setBean("tvSeries", series);

		return ActionResult.SUCCESS;
	}

	private SeriesBean getSeries(String seriesId)
	{
		for (SeriesBean s : series)
			if (s.getId().equals(seriesId))
				return s;

		return null;
	}

	private List<SeriesBean> getSeriesList()
	{
		List<SeriesBean> seriesBeanList = new ArrayList<SeriesBean>();

		List<Series> seriesList = DataUtil.getSeries();
		for (Series s : seriesList)
		{
			try
			{
				SeriesBean sb = new SeriesBean();
				deepCopySeries(sb, s);
				seriesBeanList.add(sb);
			}
			catch (Exception e)
			{
				log.error("Exception converting series: " + e.getMessage());
			}
		}

		Collections.sort(seriesBeanList);
		return seriesBeanList;
	}

	private void deepCopySeries(SeriesBean dest, Series orig) throws Exception
	{
		if (series == null)
			return;

		Set<EpisodeBean> episodeBeans = new TreeSet<EpisodeBean>();

		for (Episode e : orig.getEpisodes())
		{
			EpisodeBean eb = new EpisodeBean();
			BeanUtils.copyProperties(eb, e);
			eb.setSeriesBean(dest);
			episodeBeans.add(eb);
		}

		EpisodeBean prev = null;
		for (EpisodeBean eb : episodeBeans)
		{
			if (prev != null)
			{
				eb.setPrevEpisodeId(prev.getId());
				prev.setNextEpisodeId(eb.getId());
			}
			prev = eb;
		}

		BeanUtils.copyProperties(dest, orig);
		dest.setEpisodes(episodeBeans);
	}
}
